<?php
/**
 * 加载一个model并返回一个model对象实例（对同一个model，多次调用只会返回一个对象实例）
 * @example $ret = load_model('cms')->get_site_info($request, $response, $app);
 * @param $model_path string model路径 同require_model的第一个参数
 * @param $is_app_first bool是否优先使用应用层model，同require_model的第二个参数
 */
function load_model($model_path, $is_app_first=true) {
	if (empty($model_path)) {
		CTX()->log_error('invalid model path:'.$model_path);
		return FALSE;
	}
	static $model_dict = NULL;
	if (isset($model_dict[$model_path])) {
		$obj = $model_dict[$model_path];
	} else {
		$model_class_name = basename($model_path);
		if (!class_exists($model_class_name)) {
			require_model($model_path.'.class', $is_app_first);
		}
		$obj = new $model_class_name();
		$model_dict[$model_path] = $obj;
	}
	return $obj;
}
/**
 * 加载一个model并返回一个model对象实例（对同一个model，多次调用只会返回一个对象实例）
 * @example $ret = load_model('cms')->get_site_info($request, $response, $app);
 * @param $model_path string model路径 同require_model的第一个参数
 * @param $is_app_first bool是否优先使用应用层model，同require_model的第二个参数
 */
function load_plugin_model($plugin_path, $is_app_first=true) {
	if (empty($plugin_path)) {
		CTX()->log_error('invalid plugin model path:'.$plugin_path);
		return FALSE;
	}
	static $plugin_dict = NULL;
	if (isset($plugin_dict[$plugin_path])) {
		$obj = $plugin_dict[$plugin_path];
	} else {
		$plugin_class_name = basename($plugin_path);
		if (!class_exists($plugin_class_name)) {
			require_plugin($plugin_path.'/models/'.$plugin_class_name.'.class', $is_app_first);
		}
		$obj = new $plugin_class_name();
		$plugin_dict[$plugin_path] = $obj;
	}
	return $obj;
}
/**
 * 删除本地和浏览器中name对应的cookie
 * @param string $name cookie的名称
 * @param boolean $pub 是否公共cookie
 */
function del_cookie($name,$pub=false){
	unset($_COOKIE[$name]);
	$GLOBALS['context']->set_cookie($name,'',-42000,$pub);
}
/**
 * 清除全部或部分session
 * @param string $name 清除 $name对应的session，如果为NULL，清除全部的session，默认为NULL.
 * @param $pub 是否公共session，仅对name不为空有效
 */
function clean_session($name=null, $pub=false){
		if(isset($GLOBALS['context']->app['mode']) && $GLOBALS['context']->app['mode']==='func'){
			$GLOBALS['context']->sess_init=false;
			return;
		}
		if($name) {
			$GLOBALS['context']->init_session();
			if(! $pub) $name='fAp'.$GLOBALS['context']->app_name . $name;
			unset($_SESSION[$name]);
		}else {
			session_start();
			$_SESSION = array();
			$params=session_get_cookie_params();
			setcookie(session_name(), '', time() - 42000,$params["path"], $params["domain"]);
			session_destroy();
		}
}

/**
 * 得到 防止  跨站请求伪造(CSRF) 值，用于ajax生成dtsg_id_cffa，dtsg_ck_cffa的值。
 * @param string $form_id post表单id
 * @param string $id  id
 * @param string $ck  校验码
 */
function get_dtsg($form_id,& $dtsg_id, &$dtsg_ck){
	$id=time();
	$dtsg_id= crc32($id . $form_id . $id);
	$dtsg_ck=hash_hmac('MD5',$dtsg_id,APP_SALT);
}
/**
 * 输出防止  跨站请求伪造(CSRF) 隐藏域，必须在<form> </form>之间调用。
 * @param string $form_id post表单id，默认'cffa'
 */
function put_dtsg_to_form($form_id='cffa'){
	get_dtsg($form_id,$id,$ck);
	echo "<input type='hidden' name='dtsg_id_{$form_id}' value='{$id}' />";
	echo "<input type='hidden' name='dtsg_ck_{$form_id}' value='{$ck}' />";
}
/**
 * 校验 防止 跨站请求伪造(CSRF) 值
 * @param array $request	包含dtsg_id，dtsg_ck的输入请求数组。
 * @param string $form_id  post表单id，必须和put_anti_csrf，get_anti_csrf函数参数$form_id相同的值。
 * @return boolean true：合法，false：非法。
 */
function check_dtsg(& $request,$form_id='cffa'){
	$id="dtsg_id_{$form_id}";
	$ck="dtsg_ck_{$form_id}";
	if(! isset($request[$id]) || ! isset($request[$ck])) return false;
	$id=$request[$id];
	$ck=$request[$ck];
	return $id && $ck && $ck==hash_hmac('MD5',$id,APP_SALT) ;
}
/**
 * 返回浏览器的IP地址，依次查找HTTP_CLIENT_IP、HTTP_X_FORWARDED_FOR、REMOTE_ADDR的值，如果找不到IP，返回NULL
 */
function get_client_ip(){
   if (getenv("HTTP_CLIENT_IP") && strcasecmp(getenv("HTTP_CLIENT_IP"), "unknown"))
      return getenv("HTTP_CLIENT_IP");
   else if (getenv("HTTP_X_FORWARDED_FOR") && strcasecmp(getenv("HTTP_X_FORWARDED_FOR"), "unknown"))
       return getenv("HTTP_X_FORWARDED_FOR");
   else if (getenv("REMOTE_ADDR") && strcasecmp(getenv("REMOTE_ADDR"), "unknown"))
       return getenv("REMOTE_ADDR");
   else if (isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'], "unknown"))
       return $_SERVER['REMOTE_ADDR'];
   else
       return NULL;
}

/**
 * 设置http返回状态
 * @param integer $code http状态码
 */
function set_http_status($code) {
    static $_http_status = array(
        // Informational 100
        100 => 'Continue',
        101 => 'Switching Protocols',
        // Success 200
        200 => 'OK',
        201 => 'Created',
        202 => 'Accepted',
        203 => 'Non-Authoritative Information',
        204 => 'No Content',
        205 => 'Reset Content',
        206 => 'Partial Content',
        // Redirection 300
        300 => 'Multiple Choices',
        301 => 'Moved Permanently',
        302 => 'Moved Temporarily ',
        303 => 'See Other',
        304 => 'Not Modified',
        305 => 'Use Proxy',
        307 => 'Temporary Redirect',
        //client Error 400
        400 => 'Bad Request',
        401 => 'Unauthorized',
        402 => 'Payment Required',
        403 => 'Forbidden',
        404 => 'Not Found',
        405 => 'Method Not Allowed',
        406 => 'Not Acceptable',
        407 => 'Proxy Authentication Required',
        408 => 'Request Timeout',
        409 => 'Conflict',
        410 => 'Gone',
        411 => 'Length Required',
        412 => 'Precondition Failed',
        413 => 'Request Entity Too Large',
        414 => 'Request-URI Too Long',
        415 => 'Unsupported Media Type',
        416 => 'Requested Range Not Satisfiable',
        417 => 'Expectation Failed',
        //server Error 500
        500 => 'Internal Server Error',
        501 => 'Not Implemented',
        502 => 'Bad Gateway',
        503 => 'Service Unavailable',
        504 => 'Gateway Timeout',
        505 => 'HTTP Version Not Supported',
        509 => 'Bandwidth Limit Exceeded'
    );
    if(array_key_exists($code,$_http_status)) {
        header("HTTP/1.1 {$code} {$_http_status[$code]}");
    }
}
/**
 * 得到$action对应的URL
 * @param string $action
 * @param boolean $is_control 是否是控件action
 */
function get_app_url_path($action,$is_control=false){
		$ctx=$GLOBALS['context'];
		if($is_control){
			if($ctx->from_index)	$loc=$ctx->get_app_conf('base_url');
			else  $loc=$ctx->get_app_conf('base_url').'app/ctl/';
		}else{
			if($ctx->from_index)	$loc=$ctx->get_app_conf('base_url');
			else{
				$path=$grp=$act=NULL;
				$ctx->get_path_grp_act($action,$path,$grp,$act);
				if(! $grp)	$grp=$ctx->app_script;
				if(! $path)	$path=$ctx->app_path;
				$loc=$ctx->get_app_conf('base_url')."app/{$path}{$grp}.". $ctx->get_app_conf('php_ext') ;
			}
		}
		return 	$loc;
}
/**
 * 得到$action对应的query数组
 * @param string $action
 * @param boolean $is_control 是否是控件action
 */
function get_app_url_query($action,$is_control=false){
		$ctx=$GLOBALS['context'];
		if($is_control){
			if(! $action)	$action=$ctx->app['ctl'];
			if(! $action) $action='do_index';
			if($ctx->from_index) $result=array('app_act'=>'ctl/index/do_index','app_ctl'=>$action);
			else  $result=array('app_ctl'=>$action);
		}else{
			if(! $action)	$action=$ctx->app['path'].$ctx->app['grp'].'/'.'do_index';
			$result=array('app_act',$action);
		}
		return $result;
}